﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Windows.Forms;

namespace CANLib
{
    /// <summary>
    /// Represents a single packet from a CAN-Bus
    /// </summary>
    public class CANPacket
    {
        #region ctor

        public CANPacket()
        {

        }

        public CANPacket(UInt16 ID, byte DLC, byte[] data)
        {
            this.mID = ID;
            this.mDLC = DLC;
            this.mData = data;

            if (!CANPacket.mValueFormats.ContainsKey(this.mID))
            {
                CANPacket.mValueFormats.Add(this.mID, ValueFormat.FMT_UNKNOWN);
            }
        }

        #endregion

        #region Members

        private UInt16 mID = 0;
        private byte mDLC = 0;
        private byte[] mData = new byte[8];

        private static Dictionary<ushort, ValueFormat> mValueFormats = new Dictionary<ushort, ValueFormat>();

        #endregion

        #region Properties

        /// <summary>
        /// Gets the ID of this packet
        /// </summary>
        public UInt16 ID
        {
            get
            {
                return mID;
            }
        }

        //----------------------------------------------------------------------------------------

        /// <summary>
        /// Gets the length of the data of this packet
        /// </summary>
        public byte DLC
        {
            get
            {
                return mDLC;
            }
        }

        //----------------------------------------------------------------------------------------

        /// <summary>
        /// Gets the data of this packet
        /// </summary>
        public byte[] Data
        {
            get
            {
                return mData;
            }
        }

        //----------------------------------------------------------------------------------------

        /// <summary>
        /// Gets or sets the format of the data for all packets with the same ID
        /// </summary>
        public ValueFormat Format
        {
            get
            {
                return CANPacket.mValueFormats[this.mID];
            }
            set
            {
                if (!CANPacket.mValueFormats.ContainsKey(this.mID))
                {
                    CANPacket.mValueFormats.Add(this.mID, value);
                }
                else
                {
                    CANPacket.mValueFormats[this.mID] = value;
                }
            }
        }

        //----------------------------------------------------------------------------------------

        #endregion

        #region Operators

        /// <summary>
        /// Only convenient overloaded function for Equals(CANPacket)
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns>Returns true if the IDs of the packets are equal</returns>
        /*public bool operator ==(CANPacket a, CANPacket b)
        {
            return a.Equals(b);
        }*/

        #endregion

        #region Methods

        /// <summary>
        /// Checks if two packets have the same ID
        /// </summary>
        /// <param name="obj">Another packet for testing</param>
        /// <returns>True if the IDs of the packets are equal otherwise false</returns>
        public override bool Equals(object obj)
        {
            if(obj is CANPacket)
            {
                return ((obj as CANPacket).mID == this.mID);
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Returns the data as formated string
        /// </summary>
        /// <returns>String with the formated data of this packet (format is defined by the property Format)</returns>
        public override string ToString()
        {
            string line = "";

            try
            {
                if (this.mData != null)
                {
                    //Check for type of entry
                    switch (CANPacket.mValueFormats[this.mID])
                    {
                        case ValueFormat.FMT_DOUBLE:
                            line = BitConverter.ToDouble(this.mData, 0).ToString("F3");
                            break;

                        case ValueFormat.FMT_INTEGER:
                            line = BitConverter.ToInt32(this.mData, 0).ToString();
                            break;

                        case ValueFormat.FMT_STRING:
                            line = "\"" + BitConverter.ToString(this.mData, 0) + "\"";
                            break;

                        case ValueFormat.FMT_UNKNOWN:
                            //Add bytes to display string
                            foreach (byte b in this.mData)
                            {
                                line += "0x" + b.ToString("X2") + ";";
                            }

                            //Remove last ;
                            line.TrimEnd(';');
                            break;
                    }
                }//if
            }
            catch (ArgumentException ex)
            {
                line = "Illegal Format";
            }


            return line;
        }

        #endregion

        #region Events

        #endregion
    }
}
